`include "ascon_define.v"

module `P12
(
     input                                       clk_i,
     input                                       rst_n_i,

     input                                       p12_en_i,
     input                                       p12_vld_i,

     input                            [`S_W-1:0] p12_s_i,

     output                           [`S_W-1:0] p12_s_o,
     output                                      p12_vld_o
);

wire                              [`PC_CR_W-1:0] r_cr_i [12-1:0];
wire                                  [`S_W-1:0] r_s_i [12-1:0];
wire                                  [`S_W-1:0] r_s_o [12-1:0];
reg                                   [`S_W-1:0] r_s_r [12-1:0];

wire                                    [12-1:0] p12_vld_en_w;

assign p12_s_o          = r_s_r[11];

assign r_cr_i[0]        = `PC_CR_W'hf0;
assign r_cr_i[1]        = `PC_CR_W'he1;
assign r_cr_i[2]        = `PC_CR_W'hd2;
assign r_cr_i[3]        = `PC_CR_W'hc3;
assign r_cr_i[4]        = `PC_CR_W'hb4;
assign r_cr_i[5]        = `PC_CR_W'ha5;
assign r_cr_i[6]        = `PC_CR_W'h96;
assign r_cr_i[7]        = `PC_CR_W'h87;
assign r_cr_i[8]        = `PC_CR_W'h78;
assign r_cr_i[9]        = `PC_CR_W'h69;
assign r_cr_i[10]       = `PC_CR_W'h5a;
assign r_cr_i[11]       = `PC_CR_W'h4b;


`SINGLE_BIT_ANY_CYC
    #(
     .CYC_N                            (12                                     )
     )
u_single_bit_12_cyc
     (
     .clk_i                            (clk_i                                  ),
     .rst_n_i                          (rst_n_i                                ),
     .en_i                             (p12_en_i                               ),
     .dat_d_i                          (p12_vld_i                              ),
     .dat_q_o                          (p12_vld_o                              ),
     .vld_o                            (p12_vld_en_w                           )
     );

genvar index;

generate
for (index = 0;index < 12; index = index + 1)
begin :U_P12_ROUND_LOOP

`ROUND
u_round
    (
    .cr_i                              (r_cr_i[index]                          ),
    .s_i                               (r_s_i[index]                           ),
    .s_o                               (r_s_o[index]                           )
);

if (index == 0)

assign r_s_i[0]         = p12_s_i;

else if(index < 12)

assign r_s_i[index]     = r_s_r[index-1];

always @(posedge clk_i or negedge rst_n_i)
begin : R_S_R_PROG
  if (rst_n_i == 1'b0)
    r_s_r[index]        <= {`S_W{1'b0}};
  else if ((p12_en_i == 1'b1)&&(p12_vld_en_w[index] == 1'b1))
    r_s_r[index]        <= r_s_o[index];
  else
    r_s_r[index]        <= r_s_r[index];
end

end

endgenerate
endmodule